package top.huiwow.utils;

import com.alibaba.fastjson.JSON;
import net.minecraft.server.v1_8_R3.NBTTagCompound;
import org.bukkit.ChatColor;
import org.bukkit.craftbukkit.v1_8_R3.inventory.CraftItemStack;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import top.huiwow.GameCore;
import top.huiwow.items.AkaishiBaseItem;
import top.huiwow.items.ItemStats;

import java.util.*;

public class ItemBuilder {
    /*public static ItemStack getHyperion() {
        Map<String, Integer> statsModifier = new HashMap<>();
        statsModifier.put("Damage", 260);
        statsModifier.put("Strength", 150);
        statsModifier.put("Intelligence", 350);
        return build(Material.IRON_SWORD, "Hyperion", Rarity.LEGENDARY, "hype",
                statsModifier
                , ItemType.Weapon, true);
    }*/

    /*public static ItemStack getTerminator() {
        Map<String, Integer> statsModifier = new HashMap<>();
        statsModifier.put("Damage", 310);
        statsModifier.put("Strength", 50);
        statsModifier.put("Crit Chance", 250);
        return build(Material.BOW, "Terminator", Rarity.LEGENDARY, "term", statsModifier,
                ItemType.Weapon, true);
    }*/

    public static ItemStack build(AkaishiBaseItem abi) {
        ItemStack item = new ItemStack(abi.type);
        List<String> lore = new ArrayList<>();


        Enchantment enchantment;

        ItemMeta meta = item.getItemMeta();
        meta.setDisplayName(abi.rarity.color.toString() + ChatColor.BOLD + abi.name);
        meta.addItemFlags(ItemFlag.HIDE_ENCHANTS);

        lore.addAll(generateItemLoreByStat(abi.itemStats));
        if (!Objects.equals(abi.extraLore, "")) {
            lore.add(abi.extraLore);
        }

        lore.add("");
        lore.add(abi.rarity.color.toString() + ChatColor.BOLD + abi.rarity.name());


        meta.setLore(lore);
        meta.spigot().setUnbreakable(true);

        item.setItemMeta(meta);
        net.minecraft.server.v1_8_R3.ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
        NBTTagCompound compound = nmsItem.hasTag() ? nmsItem.getTag() : new NBTTagCompound();

        compound.setString("internal_name", abi.internalName);
        compound.setString("item_type", abi.itemType.name());
        compound.setString("stats_modifier", JSON.toJSONString(abi.itemStats));
        nmsItem.setTag(compound);
        ItemStack cis = CraftItemStack.asBukkitCopy(nmsItem);
        if (abi.shiny) {
            if (abi.type.name().toLowerCase().contains("bow")) {
                enchantment = Enchantment.LURE;
            } else {
                enchantment = Enchantment.ARROW_INFINITE;
            }
            cis.addUnsafeEnchantment(enchantment, 1);
        }

        return cis;
    }

    public static boolean isItem(ItemStack itemStack, String internal_name) {
        if (itemStack == null) return false;
        net.minecraft.server.v1_8_R3.ItemStack nmsItem = CraftItemStack.asNMSCopy(itemStack);
        if (nmsItem == null) return false;

        NBTTagCompound compound = nmsItem.hasTag() ? nmsItem.getTag() : new NBTTagCompound();
        return compound.getString("internal_name").equals(internal_name);
    }

    public static boolean isRPGItem(ItemStack itemStack) {
        if (itemStack == null) return false;
        net.minecraft.server.v1_8_R3.ItemStack nmsItem = CraftItemStack.asNMSCopy(itemStack);
        if (nmsItem == null) return false;

        NBTTagCompound compound = nmsItem.hasTag() ? nmsItem.getTag() : new NBTTagCompound();
        return compound.hasKey("internal_name");
    }

    public static String getStringCompound(ItemStack itemStack, String str) {
        net.minecraft.server.v1_8_R3.ItemStack nmsItem = CraftItemStack.asNMSCopy(itemStack);

        NBTTagCompound compound = nmsItem.hasTag() ? nmsItem.getTag() : new NBTTagCompound();
        return compound.getString(str);
    }

    public static ItemType getType(ItemStack itemStack) {
        for (ItemType itemType : ItemType.values()) {
            if (getStringCompound(itemStack, "item_type").equals(itemType.name())) {
                return itemType;
            }
        }
        return null;
    }

    public static ItemStats getStatsModifier(ItemStack itemStack) {
        if (!isRPGItem(itemStack) || getStringCompound(itemStack, "stats_modifier") == null) {
            return GameCore.emptyStatsModifier;
        }
        ItemStats itemStats = JSON.parseObject(getStringCompound(itemStack, "stats_modifier"), ItemStats.class);
        return itemStats == null ? GameCore.emptyStatsModifier : itemStats;
    }

    public static ItemStats getTotalStatsModifier(Player player) {
        ItemStats itemStats = new ItemStats();
        itemStats.intelligence = getStatsModifier(player.getItemInHand()).intelligence
                + getStatsModifier(player.getInventory().getHelmet()).intelligence
                + getStatsModifier(player.getInventory().getChestplate()).intelligence
                + getStatsModifier(player.getInventory().getLeggings()).intelligence
                + getStatsModifier(player.getInventory().getBoots()).intelligence;

        itemStats.strength = getStatsModifier(player.getItemInHand()).strength
                + getStatsModifier(player.getInventory().getHelmet()).strength
                + getStatsModifier(player.getInventory().getChestplate()).strength
                + getStatsModifier(player.getInventory().getLeggings()).strength
                + getStatsModifier(player.getInventory().getBoots()).strength;

        itemStats.defense = getStatsModifier(player.getItemInHand()).defense
                + getStatsModifier(player.getInventory().getHelmet()).defense
                + getStatsModifier(player.getInventory().getChestplate()).defense
                + getStatsModifier(player.getInventory().getLeggings()).defense
                + getStatsModifier(player.getInventory().getBoots()).defense;


        itemStats.speed = getStatsModifier(player.getItemInHand()).speed
                + getStatsModifier(player.getInventory().getHelmet()).speed
                + getStatsModifier(player.getInventory().getChestplate()).speed
                + getStatsModifier(player.getInventory().getLeggings()).speed
                + getStatsModifier(player.getInventory().getBoots()).speed;


        itemStats.critChance = getStatsModifier(player.getItemInHand()).critChance
                + getStatsModifier(player.getInventory().getHelmet()).critChance
                + getStatsModifier(player.getInventory().getChestplate()).critChance
                + getStatsModifier(player.getInventory().getLeggings()).critChance
                + getStatsModifier(player.getInventory().getBoots()).critChance;

        itemStats.critDamage = getStatsModifier(player.getItemInHand()).critDamage
                + getStatsModifier(player.getInventory().getHelmet()).critDamage
                + getStatsModifier(player.getInventory().getChestplate()).critDamage
                + getStatsModifier(player.getInventory().getLeggings()).critDamage
                + getStatsModifier(player.getInventory().getBoots()).critDamage;

        itemStats.health=getStatsModifier(player.getItemInHand()).health
                +getStatsModifier(player.getInventory().getHelmet()).health
                +getStatsModifier(player.getInventory().getChestplate()).health
                +getStatsModifier(player.getInventory().getLeggings()).health
                +getStatsModifier(player.getInventory().getBoots()).health;

        return itemStats;
    }

    public static Map<String, Integer> decodeStatModifier(String str) {
        str = str.replace("{", "").replace("}", "");
        String[] strings = str.split(",");
        Map<String, Integer> result = new HashMap<>();
        for (String s : strings) {
            String[] ss1 = s.split("=");
            result.put(ss1[0].replace(" ", ""), Integer.parseInt(ss1[1]));
        }
        return result;
    }

    public static Set<String> generateItemLoreByStat(ItemStats is) {
        Set<String> set = new HashSet<>();
        set.add(generateILBLine("Damage", is.damage));
        set.add(generateILBLine("Crit Chance", is.critChance));
        set.add(generateILBLine("Crit Damage", is.critDamage));
        set.add(generateILBLine("Strength", is.strength));
        set.add(generateILBLine("Speed", is.speed));
        set.add(generateILBLine("Defense", is.defense));
        set.add(generateILBLine("Intelligence", is.intelligence));
        set.add(generateILBLine("Health", is.health));
        return set;
    }

    private static String generateILBLine(String stat, int amount) {
        if (amount == 0) {
            return "";
        } else {
            return (stat + ": " + (amount < 0 ? "" : "+") + amount);
        }
    }
}
